package com.lingxu.base.system.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.lingxu.base.common.api.vo.Result;
import com.lingxu.base.common.util.DateUtil;
import com.lingxu.base.system.common.entity.SysLog;
import com.lingxu.base.system.common.entity.SysLogOption;
import com.lingxu.base.system.common.entity.SysLogSearchVO;
import com.lingxu.base.system.common.entity.SysLogVO;
import com.lingxu.base.system.common.mapper.SysLogMapper;
import com.lingxu.base.system.common.service.ISysLogService;
import com.lingxu.base.system.manage.vo.LoginUser;
import fr.opensagres.xdocreport.core.io.IOUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 系统日志表 服务实现类
 * </p>
 *
 * @Author zhangweijian
 * @since 2018-12-26
 */
@Service
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements ISysLogService {

	@Resource
	private SysLogMapper sysLogMapper;

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Value("${logUrl}")
	private String logUrl;

	@Override
	public IPage<SysLog> getPageList(Page<SysLog> page, SysLogOption sysLog) {
		String flag = "0";
		LoginUser userNow= (LoginUser) SecurityUtils.getSubject().getPrincipal();
		sysLog.setRegion(userNow.getRegion());
		sysLog.setUserid(userNow.getId());
		if("安全审计员".contains(userNow.getName())){
			flag = "1";
		}
		if("系统管理员".contains(userNow.getName())){
			flag = "2";
		}
		return sysLogMapper.queryPageList(page,sysLog,flag);
	}

	/**
	 * @Author ysj闫世杰
	 * @Description
	 * @Date 2023/6/19 11:36
	 * @Param: startTime
	 * @Param: endTime
	 * @return void
	 **/
	@Override
	public void downLogFilePDF(String dept,String startTime, String endTime, HttpServletRequest request, HttpServletResponse response) {
		List<SysLogVO> logList = sysLogMapper.findDownLogList(startTime,endTime);

		String path = logUrl + "/";
		File pathFile = new File(path);
		if(!pathFile.exists()) {
			pathFile.mkdirs();
		}
		// 扩大指针作用域
		Document document = null;
		ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
		OutputStream responseOutputStream = null;
		try {
			// 导出PDF文件名称
			final String pdfDocName = path + "操作日志" + ".pdf";
			// 系统路径
			File file = new File(pdfDocName);
			file.createNewFile();
			//1:建立Document对象实例
			document = new Document();
			StringBuilder filename = new StringBuilder();
			//PDF标题
			String pdfName = "操作日志";
			filename.append(pdfName).append(new SimpleDateFormat("yyyyMMddHHmm").format(new Date()));
			document.addAuthor("Author@SALES");
			document.addCreationDate();
			document.addCreator("Creator@SALES");
			document.setMargins(10, 10, 10, 10);

			PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOut);
			pdfWriter.setPdfVersion(PdfWriter.VERSION_1_4);
			// 3:打开文档
			document.open();

			//解决中文不显示问题
			BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			Font fontChina14 = new Font(bfChinese, 14);
			Font fontChina12 = new Font(bfChinese, 12);

			// 4:向文档添加内容
			Paragraph titleParagraph = new Paragraph(pdfName, fontChina14);
			// 居中
			titleParagraph.setAlignment(Element.ALIGN_CENTER);
			document.add(titleParagraph);
			// 空格
			Paragraph blank1 = new Paragraph(" ");
			document.add(blank1);
			// 表格处理及查询数据
			PdfPTable table = packageTable(logList, fontChina12);
			if (null != table) {
				document.add(table);
			}
			// 5:关闭文档
			document.close();

			//保存本地
			responseOutputStream = new FileOutputStream(file);
			fileOut.writeTo(responseOutputStream);
			//读取本地文件添加水印
			String newFilePath = path + "操作日志mark.pdf";
			//水印内容
			String content = dept + " " + DateUtil.getDateTime();
			addWaterMark(pdfDocName,newFilePath,content);
			//读取本地已生成文件通过浏览器返回
			File markPdf = new File(newFilePath);
			witerFile(request, response, markPdf, false);
			responseOutputStream.close();
//			//删除文件
			file.delete();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fileOut.close();
				responseOutputStream.close();
			} catch (IOException exception) {
				logger.error("下载异常");
			}
		}
	}


	private static void addWaterMark(String pdfFilePath, String outputFilePath,String mark) {
		try {
			// 原PDF文件
			PdfReader reader = new PdfReader(pdfFilePath);
			// 输出的PDF文件内容
			PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFilePath));

			// 字体 来源于 itext-asian JAR包
			BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", true);

			PdfGState gs = new PdfGState();
			// 设置透明度
			gs.setFillOpacity(0.3f);
			gs.setStrokeOpacity(0.4f);

			// 水印的高和宽（参数可调节）
			int textH = 75;
			int textW = 170;
			// 间隔距离（参数可调节）
			int interval = 30;
			JLabel label = new JLabel();
			label.setText(mark);
			PdfContentByte under;

			// 可添加多个水印
			Rectangle pageRect = null;
			int totalPage = reader.getNumberOfPages() + 1;
			for (int i = 1; i < totalPage; i++) {
				pageRect = reader.getPageSizeWithRotation(i);
				// 在内容上方加水印
				under = stamper.getOverContent(i);
				// 在内容下方加水印
				under.saveState();
				under.setGState(gs);
				under.beginText();
				under.setFontAndSize(baseFont, 20);
				// 水印文字成30度角倾斜
				for (int height = interval + textH; height < pageRect.getHeight();
					 height = height + textH * 3) {
					for (int width = interval + textW; width < pageRect.getWidth() + textW;
						 width = width + textW * 2) {
						under.showTextAligned(Element.ALIGN_LEFT
								, mark, width - textW,
								height - textH, 30);
					}
				}
				// 添加水印文字
				under.endText();
			}
			stamper.close();
			reader.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 写出文件
	 *
	 * @param request
	 * @param response
	 * @param file
	 * @param deleteOnExit
	 */
	private void witerFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
		response.setCharacterEncoding(request.getCharacterEncoding());
		response.setContentType("application/pdf");
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			//这里主要防止下载的PDF文件名乱码
			String fileName = URLEncoder.encode(file.getName(), "UTF-8");
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
			IOUtils.copy(fis, response.getOutputStream());
			response.flushBuffer();
		} catch (Exception e) {
			System.out.printf("下载异常111");
		} finally {
			if (fis != null) {
				try {
					fis.close();
					if (deleteOnExit) {
						file.deleteOnExit();
					}
				} catch (IOException e) {
					System.out.printf("下载异常222");
				}
			}
		}
	}

	private static PdfPTable packageTable(List<SysLogVO> sysLog, Font fontZH) {
		try {
			// 创建table下面通过table.addCell添加的时候必须添加整行内容的所有列
			PdfPTable table = new PdfPTable(4);
			//第一行是列表名
			table.setHeaderRows(1);
			table.getDefaultCell().setHorizontalAlignment(1);
			float[] width = new float[]{80,60,200,60};
			table.setWidths(width);
			if (null != sysLog && sysLog.size() > 0) {
				List<SysLogVO> newProcessVoList = new ArrayList<>();
				SysLogVO processVo = new SysLogVO();
				processVo.setCreatetime("创建时间");
				processVo.setIp("IP");
				processVo.setLogcontent("日志内容");
				processVo.setRealname("用户名称");
				newProcessVoList.add(processVo);

				for (SysLogVO tableProcessVo : sysLog) {
					SysLogVO newProcessVo = new SysLogVO();
					BeanUtil.copyProperties(tableProcessVo, newProcessVo);
					newProcessVoList.add(newProcessVo);
				}
				//遍历List 获取每一列的数据，填充到pdfTable中
				newProcessVoList.forEach(vo -> {
					table.addCell(createCell(vo.getCreatetime(), fontZH));
					table.addCell(createCell(vo.getIp(), fontZH));
					table.addCell(createCell(vo.getLogcontent(), fontZH));
					table.addCell(createCell(vo.getRealname(), fontZH));
				});
			}
			//cell跨页
			table.setKeepTogether(false);
			table.setSplitLate(false);
			table.setSplitRows(true);
			return table;
		} catch (Exception e) {
			return null;
		}
	}
	private static PdfPCell createCell(String value, Font fontZH) {
		PdfPCell cell = new PdfPCell();
		cell.setPhrase(new Phrase(value, fontZH));
		cell.setColspan(1);
		cell.setUseAscender(true);
		cell.setUseDescender(true);
		//水平居中
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		//垂直居中
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		return cell;
	}





	@Override
	public IPage<SysLog> getPTLogPageList(Page<SysLog> page, SysLogSearchVO vo) {
		LoginUser userNow= (LoginUser) SecurityUtils.getSubject().getPrincipal();
		vo.setRegion(userNow.getRegion());
		vo.setUserid(userNow.getId());
		return sysLogMapper.getPTLogPageList(page,vo);
	}



	@Override
	public Result findBackUpLogs(Integer limit,Integer page,String dateTime) {
		try {
			Page<Map> logPage = new Page<>(page,limit);
			IPage<Map> data = sysLogMapper.findBackUpLogs(logPage,dateTime);
		    return Result.ok(data,"查询成功");
		}catch (Exception e){
		    logger.error("数据查询异常",e);
		    return Result.error("查询异常");
		}
	}


	@Override
	public Result createBackUpFile() {
		try {
			String date = DateUtil.getDate("yyyy_MM_dd");
			//日志保存在服务器位置
			String path = "'C:\\dmdbms\\data\\DAMENG\\bak\\" +
					date.replace("_","") + "\\bak_full_" + date + "_" + System.currentTimeMillis() + "'";
			sysLogMapper.createBackUpFile(path);
		    return Result.ok("操作成功");
		}catch (Exception e){
		    logger.error("操作异常",e);
		    return Result.error("操作异常");
		}
	}
}
